import json
from dataclasses import dataclass

import requests
from redis import RedisCluster, Redis
from redis.cluster import ClusterNode


@dataclass
class UpdateStatusParams:
    process: any = None
    status: str = None
    error: str = None
    zipPath: str = None
    zipSize: int = None
    zipName: str = None
    fileList: list = None
    execStartTime: str = None
    execEndTime: str = None
    procedure: str = None
    remark: str = None
    shared_dict: dict = None


def redis_listener(queue, redis_util, shared_dict):
    while True:
        try:
            msg = queue.get()
            if msg is not None:
                if msg == "CALLBACK":
                    redis_util.callback(shared_dict=shared_dict, isEnd=True)
                else:
                    param: UpdateStatusParams = msg
                    param.shared_dict = shared_dict
                    redis_util.update_status(param)
            elif msg is None:
                break
            else:
                continue
        except Exception as e:
            print(e)
            continue


class RedisUtil:
    def __init__(self, base_config):
        try:
            if len(base_config['redis']['nodes']) > 1:
                self.redis_session = RedisCluster(
                    startup_nodes=[ClusterNode(host=cn['host'], port=cn['port']) for cn in
                                   base_config['redis']['nodes']],
                    password=base_config['redis']['password'],
                    decode_responses=True)
            else:
                self.redis_session = Redis(host=base_config['redis']['nodes'][0]['host'],
                                           port=base_config['redis']['nodes'][0]['port'],
                                           password=base_config['redis']['password'])
            print("初始化:redisUtil")
        except Exception as e:
            print(e)
            print("初始化失败:redisUtil")
            exit(1)

    def add_token(self, account, token):
        self.redis_session.set(f"token_{account}", token)

    def remove_status(self, redis_key):
        self.redis_session.delete(redis_key)

    def update_status(self, param: UpdateStatusParams):
        if param.shared_dict is None:
            shared_dict = {}
        else:
            shared_dict = param.shared_dict
        if param.remark is not None:
            print(param.remark)
        if 'requestCode' not in shared_dict or shared_dict['requestCode'] == "":
            webReqId = 'xcapture_status'
        else:
            webReqId = shared_dict['requestCode']
        m = self.redis_session.get(webReqId)
        if m is None:
            m = {}
        else:
            m = json.loads(m)
        if param.process is not None:
            m["process"] = param.process
        if param.status is not None:
            m["status"] = param.status
        if param.error is not None:
            m["error"] = param.error
        if param.zipPath is not None:
            m["zipPath"] = param.zipPath
        if param.zipSize is not None:
            m["zipSize"] = param.zipSize
        if param.fileList is not None:
            m["fileList"] = param.fileList
        if param.execStartTime is not None:
            m["execStartTime"] = param.execStartTime
        if param.execEndTime is not None:
            m["execEndTime"] = param.execEndTime
        if param.procedure is not None:
            m["procedure"] = param.procedure
        if param.zipName is not None:
            m["zipName"] = param.zipName
        self.redis_session.set(webReqId, json.dumps(m))
        if param.error is not None and 'callbackUrl' in shared_dict and shared_dict['callbackUrl'] is not None:
            self.callback(shared_dict)

    def get_status(self, shared_dict=None):
        if shared_dict is not None and 'requestCode' in shared_dict and shared_dict['requestCode'] is not None:
            m = self.redis_session.get(shared_dict['requestCode'])
        else:
            m = self.redis_session.get("xcapture_status")
        return m

    def callback(self, shared_dict, isEnd=False):
        try:
            status = self.get_status(shared_dict=shared_dict)
            res_json = json.loads(status)
            data = {
                "requestCode": shared_dict['requestCode'],
                "process": 100 if isEnd else res_json.get("process", ""),
                "status": res_json.get("status", ""),
                "error": res_json.get("error", ""),
                "zipPath": res_json.get("zipPath", ""),
                "zipSize": res_json.get("zipSize", 0),
                "zipName": res_json.get("zipName", ""),
                "fileList": [{
                    "filePath": item.get("filePath", ""),
                    "count": item.get("count", 0),
                    "fileCreatedAt": item.get("fileCreatedAt", ""),
                    "fileSize": item.get("fileSize", 0),
                    "fileName": item.get("fileName", "")} for item in res_json.get("fileList", [])],
            }
            print(f"回掉数据：{data}")
            res = requests.request(url=shared_dict['callBackUrl'], method="POST", json=data,
                                   headers={"Content-Type": "application/json"})
            print(res.text)
        except Exception as e:
            print(f"回掉报错：{e}")
